perm filename FLKSRT.FAI[MUD,SYS] blob
sn#553535 filedate 1981-01-03 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00013 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00003 00002 TITLE SORT Definitions.
C00004 00003 Storage allocations.
C00010 00004 READ FILENAMES
C00014 00005 Read in all strings in input file.
C00018 00006 Sort the strings using algorithm 5.2.2-Q in Knuth, "quicksort".
C00022 00007 Continue sorting: Q4, Q5, Q6.
C00024 00008 Continue sorting: Q7, Q8.
C00026 00009 Continue sorting: Q8B, Q8C, Q9.
C00029 00010 Write out sorted file: WRITEM.
C00033 00011 Subroutines: GETCH, PUTWD, PUTCH, ERROR, DUP, PUTDUP, NXTDG.
C00037 00012 GETFIL NOLOOK NOENTR FERROR
C00041 00013 SAVSTR RSTSTR
C00043 ENDMK
C⊗;
TITLE SORT ;Definitions.
AC0←←0
AC1←1
AC2←2
BEFORE←3
BPTR←←4
CHAR←←5
WD←←6
PREV←←7
PART1←4
PART2←5
PART3←6
PART4←7
PART5←10
PART6←11
PART7←12
AFTER←13
R←14
I←15
J←16
P←17
CR←←15
LF←←12
TAB←←11
FF←←14
MIN←←10 ;the minimum number of elements for using quicksort
DEFINE ERRMSG(MSG)
{PUSHJ P, [MOVEM AC1,SAVEAC
MOVEI AC1,[ASCIZ \MSG\]
JRST ERROR]}
;Storage allocations.
PDLEN←←=100
PDLIST: BLOCK PDLEN
IBUF: BLOCK 3 ;buffer header for reading in WORDS.TXT
OBUF: BLOCK 3 ;buffer header for writing out WORDS.SRT
INPPN: 0
INFILE: BLOCK 4 ;LOOKUP block
OUTPPN: 0
OUTFIL: BLOCK 4 ;ENTER block
NIBUFS←←2
BUFI: BLOCK 203*NIBUFS
NOBUFS←←4
BUFO: BLOCK 203*NOBUFS
repeat 0,<
;TEXT is a block for storing the characters of the strings being sorted
TLEN←←100000
TEXT: OCT 400000000000 ;a key of -∞
BLOCK TLEN
>
;LST is a block for keeping the (somewhat) sorted list of strings.
; The left half of a word contains the negative of the length of the
; text for that string. The right half contains a ptr to its text.
LSTLEN←←=22100
LST: XWD -1,0-1
BLOCK LSTLEN
LFT: LST+1 ;address of the leftmost element of the sublist under consideration
RGT: 0 ;address of the rightmost element of the sublist under consideration
LAST: 0
SAVEAC: 0 ;place for saving AC1 upon detection of an error
COUNT: 0 ;count of the number of words going into output file
DIGITS: BLOCK 4 ;block for holding asciz digits of a number
TEXTP: 0 ;PTR TO SPACE FOR STORING TEXT OF STRINGS
TEXTP1: 0 ;POINTER TO WORD BEFORE TEXT SPACE
REPEAT 0,<
SHF1: 0↔ 1↔ 2↔ 3↔ 103↔ 5↔ 6↔ 7 ;0
10↔ 11↔ 12↔ 13↔ 14↔ 15↔ 16↔ 17 ;10
173↔ 152↔ 22↔ 153↔ 24↔ 25↔ 26↔ 27 ;20
30↔ 31↔ 110↔ 33↔ 34↔ 35↔ 36↔ 111 ;30
40↔ 41↔ 42↔ 43↔ 172↔ 45↔ 46↔ 47 ;40
50↔ 51↔ 52↔ 53↔ 54↔ 55↔ 56↔ 57 ;50
60↔ 61↔ 62↔ 63↔ 64↔ 65↔ 66↔ 67 ;60
70↔ 71↔ 72↔ 73↔ 74↔ 75↔ 76↔ 77 ;70
100↔ 101↔ 104↔ 106↔ 112↔ 114↔ 116↔ 120 ;100
122↔ 124↔ 126↔ 130↔ 132↔ 134↔ 136↔ 140 ;110
142↔ 144↔ 146↔ 150↔ 154↔ 156↔ 160↔ 162 ;120
164↔ 166↔ 170↔ 4↔ 20↔ 21↔ 23↔ 32 ;130
37↔ 102↔ 105↔ 107↔ 113↔ 115↔ 117↔ 121 ;140
123↔ 125↔ 127↔ 131↔ 133↔ 135↔ 137↔ 141 ;150
143↔ 145↔ 147↔ 151↔ 155↔ 157↔ 161↔ 163 ;160
165↔ 167↔ 171↔ 44↔ 174↔ 175↔ 176↔ 177 ;170
SHF2: 0↔ 1↔ 2↔ 3↔ 133↔ 5↔ 6↔ 7 ;0
10↔ 11↔ 12↔ 13↔ 14↔ 15↔ 16↔ 17 ;10
134↔ 135↔ 22↔ 136↔ 24↔ 25↔ 26↔ 27 ;20
30↔ 31↔ 137↔ 33↔ 34↔ 35↔ 36↔ 140 ;30
40↔ 41↔ 42↔ 43↔ 173↔ 45↔ 46↔ 47 ;40
50↔ 51↔ 52↔ 53↔ 54↔ 55↔ 56↔ 57 ;50
60↔ 61↔ 62↔ 63↔ 64↔ 65↔ 66↔ 67 ;60
70↔ 71↔ 72↔ 73↔ 74↔ 75↔ 76↔ 77 ;70
100↔ 101↔ 141↔ 4↔ 102↔ 142↔ 103↔ 143 ;100
32↔ 37↔ 104↔ 144↔ 105↔ 145↔ 106↔ 146 ;110
107↔ 147↔ 110↔ 150↔ 111↔ 151↔ 112↔ 152 ;120
113↔ 153↔ 114↔ 154↔ 115↔ 155↔ 116↔ 156 ;130
117↔ 157↔ 120↔ 160↔ 121↔ 161↔ 122↔ 162 ;140
123↔ 163↔ 21↔ 23↔ 124↔ 164↔ 125↔ 165 ;150
126↔ 166↔ 127↔ 167↔ 130↔ 170↔ 131↔ 171 ;160
132↔ 172↔ 44↔ 20↔ 174↔ 175↔ 176↔ 177 ;170
>;END REPEAT 0
SHF1: 17↔ 17↔ 41↔ 42↔ 41↔ 17↔ 43↔ 42 ;0
44↔ 2↔ 17↔ 17↔ 17↔ 17↔ 17↔ 44 ;10
72↔ 63↔ 57↔ 63↔ 43↔ 42↔ 17↔ 17 ;20
17↔ 17↔ 43↔ 53↔ 17↔ 17↔ 44↔ 43 ;30
4↔ 43↔ 17↔ 17↔ 72↔ 17↔ 17↔ 17 ;40
10↔ 12↔ 1↔ 17↔ 14↔ 6↔ 74↔ 16 ;50
20↔ 21↔ 22↔ 23↔ 24↔ 25↔ 26↔ 27 ;60
30↔ 31↔ 17↔ 17↔ 17↔ 17↔ 17↔ 44 ;70
100↔ 41↔ 42↔ 43↔ 44↔ 45↔ 46↔ 47 ;100
50↔ 51↔ 52↔ 53↔ 54↔ 55↔ 56↔ 57 ;110
60↔ 61↔ 62↔ 63↔ 64↔ 65↔ 66↔ 67 ;120
70↔ 71↔ 72↔ 17↔ 17↔ 17↔ 17↔ 43 ;130
17↔ 41↔ 42↔ 43↔ 44↔ 45↔ 46↔ 47 ;140
50↔ 51↔ 52↔ 53↔ 54↔ 55↔ 56↔ 57 ;150
60↔ 61↔ 62↔ 63↔ 64↔ 65↔ 66↔ 67 ;160
70↔ 71↔ 72↔ 17↔ 17↔ 17↔ 17↔ 17 ;170
COMMENT ⊗
SORTING ORDER IS:
* 1
TAB 2
SPACE 4
DASH 6
( 10
) 12
COMMA 14
SLASH 16
MISC. 17
DIGITS 20:31
LETTERS 41:72 (α=A, β=B, ε=C, λ=D)
PERIOD 74
⊗; END OF COMMEND
;READ FILENAMES
SORT: OUTSTR [ASCIZ/No SOS or ETV files please.
/]
JRST SORT1
REESET: CLRBFI
OUTSTR [ASCIZ /
Bad filename!
/]
SORT1: RESET
MOVE P,[INITP: IOWD PDLEN,PDLIST];initialize pdl ptr
MOVE AC1,JOBFF↑
MOVEM AC1,TEXTP ;POINTER TO PLACE WHERE TEXT STRS WILL GO
SUBI AC1,1
MOVEM AC1,TEXTP1 ;POINTER TO PREVIOUS WORD
ADDI AC1,4*2000 ;START WITH 4K OF WORKING TEXT SPACE
CAMG AC1,JOBREL↑ ;ALREADY GOT PLENTY OF CORE?
JRST SORT2 ;YES
CORE AC1, ;CORE UP. MAKE SURE THERE IS ROOM TO WORK WITH
ERRMSG {CANT INITIALIZE CORE SIZE}
SORT2:
MOVE AC1,TEXTP
SETZM 1(AC1) ;CLEAR TEXT SPACE
HRLI AC1,1(AC1)
ADDI AC1,2
BLT AC1,@JOBREL
MOVSI AC1,400000
MOVEM AC1,@TEXTP ;STRING OF -∞
MOVSI AC1,-1
HRR AC1,TEXTP1 ;PTR TO STRING OF -∞
MOVEM AC1,LST
MOVEI AC1,LST+1
MOVEM AC1,LFT
SETZM RGT
SETZM LAST
;READ INPUT & OUTPUT FILENAMES
GETIN: OUTSTR [ASCIZ/Input file: /]
MOVEI R,INFILE
PUSHJ P,GETFIL
JRST REESET
INIT 1,0
SIXBIT /DSK/
IBUF
ERRMSG {INIT FAILED ON DSK}
MOVE AC1,INPPN
MOVEM AC1,INFILE+3
LOOKUP 1,INFILE
JRST NOLOOK
MOVEI AC1,BUFI
MOVEM AC1,JOBFF↑
INBUF 1,NIBUFS
GETOUT: OUTSTR [ASCIZ/Output file: /]
MOVEI R,OUTFIL
PUSHJ P,GETFIL
JRST REESET
INIT 2,0
SIXBIT /DSK/
XWD OBUF,0
ERRMSG {INIT FAILED ON DSK}
MOVE AC1,OUTPPN
MOVEM AC1,OUTFIL+3
LOOKUP 2,OUTFIL
JRST GETOU1
OUTSTR [ASCIZ/Output file already exists.
Type Y to REPLACE? /]
INCHRW AC1
CAIN AC1,CR
JRST GETOU2
CAIE AC1,"Y"
CAIN AC1,"y"
JRST GETOU3
OUTSTR [ASCIZ/
/]
JRST GETOUT
GETOU2: INCHRW AC1 ;READ LF AFTER CR
OUTSTR [ASCIZ/
/]
JRST GETOUT
GETOU3: OUTSTR [ASCIZ/
/]
GETOU1: CLOSE 2, ;NO RA MODE ACCESS PLEASE
MOVE AC1,OUTPPN
MOVEM AC1,OUTFIL+3
SETZM OUTFIL+2
ENTER 2,OUTFIL
JRST NOENTR
MOVEI AC1,BUFO
MOVEM AC1,JOBFF↑
OUTBUF 2,NOBUFS
;Read in all strings in input file.
MOVEI AC0,"@"
MOVSI BPTR,010700
HRR BPTR,TEXTP ;initialize byte ptr for saving text of strings
MOVE WD,[XWD -LSTLEN,LST+1] ;init ptr to list of strings being sorted
OUTSTR [ASCIZ /READING.../]
GETWD: HRRZM BPTR,(WD) ;save ptr to place for text of next word
MOVE PREV,BPTR ;save byte ptr for calculating length of word
setzm atsign
GETLTR: PUSHJ P,GETCH
cain char,"@"
setom atsign#
CAIN CHAR,CR ;any char BUT CR is considered part of input word
JRST READLF
IDPB CHAR,BPTR ;save this char in TEXT
JRST GETLTR ;get next char
READLF: PUSHJ P,GETCH ;read the lf that follows the cr
skipn atsign
jrst noats
outstr [asciz/String contains "@", will be truncated in output file: /]
setzm 1(bptr) ;stop outstr
outstr 1(prev)
outstr [asciz/
/]
noats:
IDPB AC0,BPTR ;put an @ after the text of this word
TLNE BPTR,760000 ;if @ is at end of word, put another @
JRST [IBP BPTR ;otherwise, put a zero byte
JRST .+2]
FINWRD: IDPB AC0,BPTR ;put another @ to fill up the last word
TLNE BPTR,760000 ;now at low order byte?
JRST FINWRD ;no
SUB PREV,BPTR ;calculate the number of words in this string
HRLM PREV,(WD) ;store the length of this string in its LST entry
MOVEI PREV,100(BPTR) ;SEE IF STILL HAVE PLENTY OF TEXT SPACE
CAMG PREV,JOBREL↑ ;NEED MORE CORE?
JRST FINWR1 ;NO
PUSH P,JOBREL↑
CORE PREV, ;YES, GET SOME
ERRMSG {CANT CORE UP}
POP P,PREV
SETZM 1(PREV) ;CLEAR NEW TEXT SPACE OBTAINED
HRLI PREV,1(PREV)
ADDI PREV,2
BLT PREV,@JOBREL↑
FINWR1: AOBJN WD,GETWD
ERRMSG {TOO MANY STRINGS.}
;Sort the strings using algorithm 5.2.2-Q in Knuth, "quicksort".
SORTEM: TLNE BPTR,760000
ERRMSG {EOF IN MIDDLE OF KEYWORD}
MOVE AC1,[377777777777] ;place a key of +∞ at the end
MOVEM AC1,1(BPTR) ; of the list of strings
MOVEM BPTR,LASTCH#
OUTSTR [ASCIZ/SAVING STRINGS.../]
PUSHJ P,SAVSTR
repeat 0,<
OUTSTR [ASCIZ/PERVERTING.../]
MOVSI BPTR,010700
HRR BPTR,TEXTP
PERM1: ILDB AC1,BPTR
MOVE AC1,SHF1(AC1)
DPB AC1,BPTR
CAME BPTR,LASTCH
JRST PERM1
>;repeat 0
MOVEI AC1,-1
HRLM AC1,(WD) ;store length of the +∞ key
HRRM BPTR,(WD) ;store text ptr for the +∞ key
SUBI WD,1 ;adjust the ptr to the last real key
HRRZM WD,RGT ; and sort up to this key
HRRZM WD,LAST
OUTSTR [ASCIZ /SORTING.../]
Q2: MOVE AC1,RGT ;if RGT-LFT < MIN then use straight
SUB AC1,LFT ; insertion sorting instead
CAIGE AC1,MIN ; of quicksort
JRST Q8 ;use straight insertion sorting
MOVE I,LFT ;I←LFT
MOVE J,RGT ;J←RGT
MOVE R,(I) ;R←R(I) (the Ith record being sorted)
MOVE PART1,1(R) ;load the current keyword string into
MOVE PART2,2(R) ; accumulators PART1 thru PART7
MOVE PART3,3(R)
MOVE PART4,4(R)
MOVE PART5,5(R)
MOVE PART6,6(R)
MOVE PART7,7(R)
Q3: HLRE AC1,R ;get negated length of current key into AC1
MOVE AC2,(J) ;put the Jth record into AC2
CAME PART1,1(AC2) ;compare the respective parts of record R
JRST [CAML PART1,1(AC2) ; and the Jth record
JRST Q4 ;Jth key ≤ key of record R
SOJA J,Q3] ;Jth key > key of record R
AOJGE AC1,Q4 ;if AC1=0 then Jth key = key of record R
CAME PART2,2(AC2)
JRST [CAML PART2,2(AC2)
JRST Q4
SOJA J,Q3]
AOJGE AC1,Q4
CAME PART3,3(AC2)
JRST [CAML PART3,3(AC2)
JRST Q4
SOJA J,Q3]
AOJGE AC1,Q4
CAME PART4,4(AC2)
JRST [CAML PART4,4(AC2)
JRST Q4
SOJA J,Q3]
AOJGE AC1,Q4
CAME PART5,5(AC2)
JRST [CAML PART5,5(AC2)
JRST Q4
SOJA J,Q3]
AOJGE AC1,Q4
CAME PART6,6(AC2)
JRST [CAML PART6,6(AC2)
JRST Q4
SOJA J,Q3]
AOJGE AC1,Q4
CAME PART7,7(AC2)
JRST [CAML PART7,7(AC2)
JRST Q4
SOJA J,Q3]
;Continue sorting: Q4, Q5, Q6.
Q4: CAMGE I,J
JRST .+3 ;I<J
MOVEM R,(I) ;I≥J. R←Ith record.
JRST Q7
MOVEM AC2,(I) ;I<J. Ith record ← Jth record
ADDI I,1 ;I←I+1
Q5: HLRE AC1,R ;get negated length of record R into AC1
MOVE AC2,(I) ;get Ith record into AC2
CAME PART1,1(AC2) ;compare Ith key with key of record R
JRST [CAMG PART1,1(AC2)
JRST Q6 ;key of record R ≤ Ith key
AOJA I,Q5] ;key of record R > Ith key
AOJGE AC1,Q6 ;AC1=0 means key of record R = Ith key
CAME PART2,2(AC2)
JRST [CAMG PART2,2(AC2)
JRST Q6
AOJA I,Q5]
AOJGE AC1,Q6
CAME PART3,3(AC2)
JRST [CAMG PART3,3(AC2)
JRST Q6
AOJA I,Q5]
AOJGE AC1,Q6
CAME PART4,4(AC2)
JRST [CAMG PART4,4(AC2)
JRST Q6
AOJA I,Q5]
AOJGE AC1,Q6
CAME PART5,5(AC2)
JRST [CAMG PART5,5(AC2)
JRST Q6
AOJA I,Q5]
AOJGE AC1,Q6
CAME PART6,6(AC2)
JRST [CAMG PART6,6(AC2)
JRST Q6
AOJA I,Q5]
AOJGE AC1,Q6
CAME PART7,7(AC2)
JRST [CAMG PART7,7(AC2)
JRST Q6
AOJA I,Q5]
Q6: CAMGE J,I
JRST .+3 ;I<J
MOVEM AC2,(J) ;I≥J. Jth record ← Ith record
SOJA J,Q3 ;J←J-1
MOVEM R,(J) ;I<J. Jth record ← record R
MOVEM J,I ;I←J
;Continue sorting: Q7, Q8.
;record R is now in its final place, dividing the list into two sublists.
;continue by sorting the smaller sublist next.
Q7: MOVE AC2,I ;AC2 ← I
ASH AC2,1 ;AC2 ← 2*I
SUB AC2,LFT ;AC2 ← 2*I - LFT
CAMLE AC2,RGT ;is 2*I - LFT ≤ RGT ? (ie I-LFT ≤ RGT -I)
JRST Q7A ;no
MOVE AC2,I ;yes
ADDI AC2,1
PUSH P,AC2 ;save (on the stack) the sublist from I+1 to RGT
PUSH P,RGT
SUBI AC2,2
MOVEM AC2,RGT ;RGT ← I-1
JRST Q2
Q7A: PUSH P,LFT ;save (on the stack) the sublist from LFT to I-1
MOVE AC2,I
SUBI AC2,1
PUSH P,AC2
ADDI AC2,2
MOVEM AC2,LFT ;LFT ← I+1
JRST Q2
;prepare to sort from LFT to RGT by straight insertion
Q8: AOS J,LFT ;J ← LFT + 1
Q8A: CAMLE J,RGT ;insert record J into the sorted list unless J > RGT
JRST Q9 ;insertion sort is finished
MOVE R,(J) ;record R ← Jth record
MOVE PART1,1(R) ;load the parts of the key of record R into ACs
MOVE PART2,2(R)
MOVE PART3,3(R)
MOVE PART4,4(R)
MOVE PART5,5(R)
MOVE PART6,6(R)
MOVE PART7,7(R)
MOVEI I,-1(J) ;I ← J-1
;Continue sorting: Q8B, Q8C, Q9.
;insertion sorting for small numbers of elements (continued).
Q8B: MOVE AC2,(I) ;put the Ith record into AC2
HLRE AC1,R ;get the length of the key of record R into AC1
CAME PART1,1(AC2) ;compare the Ith key with the key of record R
JRST [CAML PART1,1(AC2)
JRST Q8C ;key of record R ≥ Ith key
OVER: MOVE AC1,(I) ;key of record R < Ith key. move the Ith
MOVEM AC1,1(I) ; record over one to the right
SOJA I,Q8B] ;I ← I-1. get the new Ith record
AOJGE AC1,Q8C ;AC1=0 means key of record R = Ith key
CAME PART2,2(AC2)
JRST [CAML PART2,2(AC2)
JRST Q8C
JRST OVER]
AOJGE AC1,Q8C
CAME PART3,3(AC2)
JRST [CAML PART3,3(AC2)
JRST Q8C
JRST OVER]
AOJGE AC1,Q8C
CAME PART4,4(AC2)
JRST [CAML PART4,4(AC2)
JRST Q8C
JRST OVER]
AOJGE AC1,Q8C
CAME PART5,5(AC2)
JRST [CAML PART5,5(AC2)
JRST Q8C
JRST OVER]
AOJGE AC1,Q8C
CAME PART6,6(AC2)
JRST [CAML PART6,6(AC2)
JRST Q8C
JRST OVER]
AOJGE AC1,Q8C
CAME PART7,7(AC2)
JRST [CAML PART7,7(AC2)
JRST Q8C
JRST OVER]
Q8C: MOVEM R,1(I) ;found the place in the sorted list for record R
AOJA J,Q8A ;J ← J+1. get next key to be inserted
Q9: CAMN P,INITP ;is the stack of empty of sublists to be sorted?
JRST WRITEM ;yes. everything is sorted so write out the results
POP P,RGT ;no. pop a sublist off
POP P,LFT ; the stack and
JRST Q2 ; go sort it
;Write out sorted file: WRITEM.
WRITEM: SETZM COUNT ;NUMBER OF SORTED STRINGS, NOT COUNTING DUPLICATES
OUTSTR [ASCIZ/REVERTING.../]
PUSHJ P,RSTSTR ;RESTORE STRING SPACE TO ORIGINAL VALUES
REPEAT 0,<
MOVSI BPTR,010700
HRR BPTR,TEXTP
PERM2: ILDB AC1,BPTR ;GUESS WHAT THIS LOOP DOES!
MOVE AC1,SHF2(AC1)
DPB AC1,BPTR
CAME BPTR,LASTCH
JRST PERM2
>;END REPEAT 0
OUTSTR [ASCIZ /
DUPLICATES:
/]
MOVEI WD,LST+1 ;make WD point at first element of sorted list
MOVSI AFTER,AC2 ;SET UP INDEX FIELD OF INDIRECT PTR
HRR AFTER,TEXTP1 ;MAKE PREVIOUS KEY BE THAT OF -∞
NEXTWD: HRRZ BPTR,(WD) ;set up byte ptr to text of current key
HRLI BPTR,700
MOVE BEFORE,AFTER ;save indirect ptr to text of previous key
HRR AFTER,BPTR ;set up indirect ptr to text of current key
HLLZ AC2,(WD) ;put negated length of current key in left of AC2
ADDI AC2,1 ;put displacement of 1 into right half of AC2
CMPR: MOVE PART7,@AFTER ;get one part of current key and compare
CAME PART7,@BEFORE ; it to corresponding part of old key
JRST NEXTCH ;the corresponding parts are not the same
AOBJN AC2,CMPR ;they are the same. get next part of each, if any.
JRST DUP ;all parts of the previous and current keys were samm
NEXTC1: PUSHJ P,PUTCH
NEXTCH: ILDB CHAR,BPTR ;get a char of current key
CAIE CHAR,"@" ;is it a "@"?
JRST NEXTC1 ;NO
ENDWD: MOVEI CHAR,CR ;output a CR and a LF after the key in
PUSHJ P,PUTCH ; the file of sorted keys
MOVEI CHAR,LF
PUSHJ P,PUTCH
AOS COUNT ;count the number of keys (not including duplicates)
FINWD: CAMGE WD,LAST ;have we gotten to the last of the sorted keys?
AOJA WD,NEXTWD ;no. go back and get the next one.
RELEAS 2, ;yes. close the output file
RELEAS 1, ;input file
OUTSTR [ASCIZ /
/]
MOVE AC1,COUNT ;convert the number of keys to ascii
MOVE BPTR,[POINT 7,DIGITS]
PUSHJ P,NXTDG
SETZ AC2,
IDPB AC2,BPTR
OUTSTR DIGITS ;print out the number of keys (not including duplicates)
OUTSTR [ASCIZ / sorted strings./]
EXIT
;Subroutines: GETCH, PUTWD, PUTCH, ERROR, DUP, PUTDUP, NXTDG.
;get a character from the input file.
GETCH: SOSG IBUF+2 ;decrement byte count
IN 1, ;buffer emptied. get another
JRST [ILDB CHAR,IBUF+1 ;load a character into CHAR
JUMPE CHAR,GETCH ;if the char is a null, get another char
CAIN CHAR,FF ;IGNORE FORMFEEDS
JRST GETCH
POPJ P,]
STATO 1,20000 ;test for EOF
ERRMSG {UNKNOWN ERROR CONDITION CAME UP ON INPUT}
SUB P,[XWD 1,1] ;pop return address off the stack
JRST SORTEM ;go sort the keys that have been read in
;output a character to the file of sorted keys.
PUTCH: JUMPE CHAR,CPOPJ
SOSG OBUF+2 ;decrement byte count
OUT 2, ;buffer filled. output it.
JRST [IDPB CHAR,OBUF+1 ;deposit a character into the output buffer
POPJ P,]
ERRMSG {UNKNOWN ERROR CONDITION CAME UP ON OUTPUT}
;print out an error message on the tty.
ERROR: OUTSTR [CRLFS: ASCIZ /
/]
OUTSTR (AC1)
OUTSTR CRLFS
MOVE AC1,SAVEAC
EXIT 1,
;print out a duplicate string on the tty.
DUP: ILDB CHAR,BPTR
CAIN CHAR,"@"
JRST FINWD ;this is a duplicate null word
OUTSTR (BPTR) ;type out the keyword
OUTSTR [ASCIZ/
/]
JRST FINWD
;convert a number to ascii, depositing the ascii digits with the byte ptr BPTR
NXTDG: IDIVI AC1,=10 ;divide the number by =10 and
HRLM AC2,(P) ; save the remainder
JUMPE AC1,.+2 ;if the quotient is zero, the conversion is done
PUSHJ P,NXTDG ;otherwise, calculate the next digit
HLRZ AC1,(P) ;get high order digits off stack first
ADDI AC1,60 ;convert current digit to ascii
IDPB AC1,BPTR ;deposit it in ascii string
CPOPJ: POPJ P, ;get next digit, or return if all done
;GETFIL NOLOOK NOENTR FERROR
F←0
PPN←←BEFORE
CH←←CHAR
BP←←BPTR
A←←AC1
C←←AC2
;FLAGS IN LEFT HALF OF F
QUOTE←←400000
GOTEXT←←200000
GOTP←←100000
GOTPN←←40000
GETFIL: MOVEI I,6 ;limit filename to 6 chars
MOVE BP,[POINT 6,(R)]
SETZB F,(R)
SETZB PPN,1(R)
JRST TEST
DOQUOT: TLC F,QUOTE
JRST TEST
GETNAM: TRZ CH,40 ;convert char to sixbit
TRZE CH,100
TRO CH,40
SOJL I,.+2
IDPB CH,BP
TEST: INCHWL CH
CAIN CH,CR ;END OF INPUT?
JRST ENDNAM ;YES
CAIN CH,"↓"
JRST DOQUOT
TLNE F,QUOTE ;ARE WE QUOTING A NAME?
JRST GETNAM ;YES, DONT MAKE SPECIAL TESTS
CAIN CH,"]" ;END OF P,PN?
JRST ENDNAM ;YES TO ONE OF THESE
CAIN CH,"[" ;PROJECT NEXT?
JRST GETP ;YES
CAIN CH,"," ;PROGRAMMER NAME NEXT?
JRST GETPN ;YES
CAIE CH,"." ;EXTENSION NEXT?
JRST GETNAM ;NO
GETEXT: TLOE F,GOTEXT ;MAKE SURE WE DONT ALREADY HAVE AN EXTENSION
POPJ P, ;TAKE ERROR RETURN
MOVE BP,[POINT 6,1(R)]
GOON: MOVEI I,3
JRST TEST
GETP: TLOE F,GOTP ;MAKE SURE WE DONT ALREADY HAVE A PROJECT
POPJ P, ;TAKE ERROR RETURN
MOVE BP,[POINT 6,PPN] ;PUT PROJECT INTO LEFT HALF OF PPN
JRST GOON
GETPN: TLON F,GOTPN ;MAKE SURE WE DONT ALREADY HAVE A PROGRAMMER NAME
TLNN F,GOTP ;MAKE SURE WE DO HAVE A PROJECT
POPJ P, ;TAKE ERROR RETURN
SETZ C,
MOVE BP,[POINT 6,C,17] ;PUT PROGRAMMER NAME INTO RIGHT HALF OF C
JUMPLE I,GOON
LSH PPN,-6 ;RIGHT-JUSTIFY PROJECT IN LEFT HALF OF PPN
SOJG I,.-1
JRST GOON
ENDNAM: INCHRW CHAR
CAIE CHAR,LF ;FORGET INPUT AFTER "]" OR CR UP TO LF
JRST ENDNAM
TLNN F,GOTP ;PROJECT SPECIFIED?
JRST END1 ;NO
TLNN F,GOTPN ;PROGRAMMER NAME?
JRST END2 ;NO
JUMPLE I,END4 ;YES. ALREADY RIGHT JUSTIFIED?
LSH C,-6 ;NO. DO IT NOW.
SOJG I,.-1
JRST END4
END2: JUMPLE I,END5 ;PROJECT RIGHT JUSTIFIED?
LSH PPN,-6 ;NO. DO IT NOW.
SOJG I,.-1
END5: SETZ C, ;GET OWN DISK PPN
DSKPPN C,
END4: HRR PPN,C ;COMBINE P & PN IN PPN
END1: MOVEM PPN,-1(R) ;SAVE PPN
AOS (P)
POPJ P,
NOLOOK: OUTSTR [ASCIZ/LOOKUP FAILED -- /]
HRRZ A,INFILE+1 ;GET ERROR CODE
CAILE A,MAXERR
MOVEI A,MAXERR
OUTSTR @FERROR(A)
OUTSTR [ASCIZ/.
/]
JRST GETIN
NOENTR: OUTSTR [ASCIZ/ENTER FAILED -- /]
HRRZ A,OUTFIL+1 ;GET ERROR CODE
CAILE A,MAXERR
MOVEI A,MAXERR
OUTSTR @FERROR(A)
OUTSTR [ASCIZ/.
/]
JRST GETOUT
FERROR: [ASCIZ/NO SUCH FILE/]
[ASCIZ/ILLEGAL PPN/]
[ASCIZ/PROTECTION VIOLATION/]
[ASCIZ/FILE BUSY/]
MAXERR←←.-FERROR
[ASCIZ/BAD RETRIEVAL OR OTHER HORRIBLE ERROR/]
;SAVSTR RSTSTR
STRCMD: 0 ;DUMP MODE COMMAND FOR SAVING/RESTORING STRING SPACE GOES HERE
0
SAVSTR: INIT 3,17
SIXBIT /DSK/
0
ERRMSG {CANT INIT DSK}
PUSH P,PART1
PUSH P,PART2
PUSH P,PART3
PUSH P,PART4
ACCTIM PART1,
MOVEM PART1,STRFIL#
MOVSI PART2,'ZXC'
SETZB PART3,PART4
ENTER 3,PART1
ERRMSG {CANT ENTER TEMPORARY STRING FILE}
MOVE PART1,TEXTP
MOVEM PART1,STRCMD
HRRZ PART2,LASTCH
SUBI PART1,2(PART2)
HRLM PART1,STRCMD ;STORE LENGTH FIELD IN DUMP MODE COMMAND
OUT 3,STRCMD
JRST .+2
ERRMSG {OUT FAILED WHEN WRITING TEMPORARY STRING FILE}
CLOSE 3,
POP P,PART4
POP P,PART3
POP P,PART2
POP P,PART1
POPJ P,
RSTSTR:
PUSH P,PART1
PUSH P,PART2
PUSH P,PART3
PUSH P,PART4
MOVE PART1,STRFIL ;PICK UP NAME OF TEMP FILE
MOVSI PART2,'ZXC' ;AND EXTENSION
SETZ PART4,
LOOKUP 3,PART1
ERRMSG {LOOKUP FAILED FOR TEMPORARY STRING FILE}
IN 3,STRCMD
JRST .+2
ERRMSG {IN FAILED WHEN READING TEMPORARY STRING FILE}
CLOSE 3,
SETZB PART1,PART4
RENAME 3,PART1 ;DELETE TEMP FILE
OUTSTR [ASCIZ/Failed to delete temporary string file.
/]
RELEAS 3,
POP P,PART4
POP P,PART3
POP P,PART2
POP P,PART1
POPJ P,
END SORT